﻿Ext.Controller = Ext.extend(Ext.util.Observable, {

    //通过ExtControllerManager创建实例，传来的配置参数中application属性指向一个Ext.Application实例
    constructor: function (config) {
        this.addEvents(

            'instance-created',


            'instance-creation-failed',


            'instance-updated',


            'instance-update-failed',


            'instance-destroyed',


            'instance-destruction-failed'
        );

        Ext.Controller.superclass.constructor.call(this, config);

        Ext.apply(this, config || {});

        if (typeof this.model == 'string') {
            this.model = Ext.ModelMgr.getModel(this.model);
        }
    },

    
    index: function () {
        this.render('index', {
            listeners: {
                scope: this,
                edit: this.edit,
                build: this.build,
                create: this.onCreateInstance,
                destroy: this.onDestroyInstance
            }
        });
    },


    edit: function (instance) {
        var view = this.render('edit', {
            listeners: this.getEditListeners()
        });

        view.loadModel(instance);
    },

    //Callback automatically tied to the index view's 'build' event. 
    //By default this just renders the registered 'build' view
    build: function () {
        //将id为‘buile’的组件添加到应用程序的默认组件中
        this.render('build', {
            listeners: this.getBuildListeners()
        });
    },

    //Saves a phantom Model instance via its configured Proxy. 
    //Fires the 'instance-created' event if successful, the 'instance-creation-failed' event if not.
    create: function (data, options) {
        options = options || {};

        var model = this.getModel(),
            instance = new model(data),
            successCb = options.success,
            failureCb = options.failure,
            scope = options.scope || this;

        instance.save({
            scope: this,
            success: function (instance) {
                if (typeof successCb == 'function') {
                    successCb.call(scope, instance);
                }

                this.fireEvent('instance-created', instance);
            },
            failure: function (instance, errors) {
                if (typeof failureCb == 'function') {
                    failureCb.call(scope, instance, errors);
                }

                this.fireEvent('instance-creation-failed', instance, errors);
            }
        });
    },


    update: function (instance, updates, options) {
        options = options || {};

        var successCb = options.success,
            failureCb = options.failure,
            scope = options.scope || this;

        if (Ext.isObject(updates)) {
            instance.set(updates);
        }

        instance.save({
            scope: this,
            success: function (instance) {
                if (typeof successCb == 'function') {
                    successCb.call(scope, instance);
                }

                this.fireEvent('instance-updated', instance);
            },
            failure: function (instance, errors) {
                if (typeof failureCb == 'function') {
                    failureCb.call(scope, instance, errors);
                }

                this.fireEvent('instance-update-failed', instance, errors);
            }
        });
    },


    destroy: function (instance, options) {
        options = options || {};

        var successCb = options.success,
            failureCb = options.failure,
            scope = options.scope || this;

        instance.destroy({
            scope: this,
            success: function (instance) {
                if (typeof successCb == 'function') {
                    successCb.call(scope, instance);
                }

                this.fireEvent('instance-destroyed', instance);
            },
            failure: function (instance, errors) {
                if (typeof failureCb == 'function') {
                    failureCb.call(scope, instance, errors);
                }

                this.fireEvent('instance-destruction-failed', instance, errors);
            }
        });
    },


    getBuildListeners: function () {
        return {
            scope: this,
            save: this.onCreateInstance,
            cancel: this.onCancelBuild
        };
    },


    getEditListeners: function () {
        return {
            scope: this,
            save: this.onUpdateInstance,
            cancel: this.onCancelEdit
        };
    },


    onCancelEdit: function (view) {
        return this.closeView(view);
    },


    onCancelBuild: function (view) {
        return this.closeView(view);
    },


    onCreateInstance: function (view) {
        this.create(view.getValues(), {
            scope: this,
            success: function (instance) {
                this.closeView(view);
            },
            failure: function (instance, errors) {
                console.log('fail');
            }
        });
    },


    onUpdateInstance: function (view) {
        this.update(view.getRecord(), view.getValues(), {
            scope: this,
            success: function (instance) {
                this.closeView(view);
            },
            failure: function (instance, errors) {

            }
        });
    },


    onDestroyInstance: function (instance, view) {
        this.destroy(instance, {
            scope: this,
            success: function (instance) {

            },
            failure: function (instance, errors) {

            }
        });
    },


    setRenderTarget: function (target) {

        Ext.Controller.renderTarget = target;
    },

    //根据config创建一个新组件，加入target组件中做为子组件
    render: function (config, target) {
        var Controller = Ext.Controller,

            //通过Ext.ControllerManager创建实例，传来的配置参数中application属性指向一个Ext.Application实例
            application = this.application,

            //应用程序当前配置名
            profile = application ? application.currentProfile : undefined,
            profileTarget, view;

        Ext.applyIf(config, {
            profile: profile
        });

        view = Ext.ComponentMgr.create(config);//创建新组件

        if (target !== false) {

            profileTarget = profile ? profile.getRenderTarget(config, application) : target;

            //如果target未定义，则赋予它默认值，可能是应用程序配置属性或应用程序默认目标组件
            if (target == undefined) {
                target = profileTarget || (application ? application.defaultTarget : undefined);
            }

            //如果target是字符串，则表示组件id
            if (typeof target == 'string') {
                target = Ext.getCmp(target);
            }

            //如果target有add方法
            if (target != undefined && target.add) {
                if (profile) {
                    profile.beforeLayout(view, target, application);
                }

                target.add(view);//将新建的组件加入目标组件中

                if (target.layout && target.layout.setActiveItem) {
                    target.layout.setActiveItem(view);//将新组件作为目标组件的活动组件
                }

                target.doComponentLayout();

                if (profile) {
                    profile.afterLayout(view, target, application);
                }
            }
        }

        return view;
    },

    //给view注册侦听函数，事件名为itemName，响应函数为actions对象中各属性指向的函数
    control: function (view, actions, itemName) {
        if (!view || !view.isView) {
            throw 'Trying to control a view that doesnt exist';
        }

        var item = itemName ? view.refs[itemName] : view, // 绑定事件是视图
            key, value, name, child, listener;

        if (!item) {
            throw "No item called " + itemName + " found inside the " + view.name + " view.";
        }

        // 遍历动作对象
        for (key in actions) {
            value = actions[key];




            if (Ext.isObject(value) && !value.fn) {
                this.control(view, value, key);
            }
            else {

                //如果视图还绑定子视图
                if (item.refs) {
                    for (name in item.refs) {
                        child = item.refs[name];
                        if (child.isObservable && child.events[key]) {
                            child.enableBubble(key);
                        }
                    }
                }

                if (!value.fn) { // value不是带fn的对象，则它本身就是方法
                    listener = {};
                    listener[key] = value;
                    listener.scope = this;
                }
                else {
                    listener = value;
                    if (listener.scope === undefined) {
                        listener.scope = this;
                    }
                }


                item.addListener(listener); // 给视图注册监听函数
            }
        }

        return view;
    },


    getModel: function () {
        return Ext.ModelMgr.getModel(this.model);
    },


    closeView: function (view) {
        var ownerCt = view.ownerCt;

        if (ownerCt) {
            ownerCt.remove(view);
            ownerCt.doLayout();
            ownerCt.setActiveItem(ownerCt.items.last());
        }
    }
});